﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace CompilerDLL.LexicalAnalysis
{
    public class DFA_C_Program:BaseLexical 
    {
        #region 判断是否为C语言中的保留字
        /// <summary>
        /// 判断是否为保留字
        /// </summary>
        /// <param name="strToken"></param>
        /// <returns></returns>
        private bool Reserve(string strToken)
        {
            if (strToken == "main"
                 || strToken == "int"
                 || strToken == "float"
                 || strToken == "printf"
                 || strToken == "then"
                 || strToken == "else"
                 || strToken == "if"
                 || strToken == "for"
                 || strToken == "while"
                 || strToken == "do"
                 || strToken == "return"
                 || strToken == "break"
                 || strToken == "continue")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region C语言词法分析主程序
        /// <summary>
        /// 词法分析主程序
        /// </summary>
        public ArrayList LexicalMain(string txtSourceCode)
        {
            this.tokenIndexer = 0;
            this.arrayTokens = new System.Collections.ArrayList();
            this.sourceCodeChars = txtSourceCode.ToCharArray();

            try
            {
                #region 执行状态转换图
                do
                {
                    strToken = "";
                    this.ch = this.GetChar(sourceCodeChars, this.tokenIndexer);
                    if (this.ch != ' ')
                    {
                        #region(1).如果是以字母开头时，则判断为保留字或者标识符
                        //(1).如果是以字母开头时，则判断为保留字或者标识符
                        if (IsLetter(this.ch))
                        {
                            ModelTokenType modelTokenType;

                            while ((IsLetter(this.ch) || (IsDigit(this.ch))))
                            {
                                strToken = strToken + ch;

                                this.tokenIndexer++;
                                if (this.tokenIndexer == sourceCodeChars.Length)
                                {
                                    //保存识别出来的结果
                                    modelTokenType = new ModelTokenType();
                                    if (this.Reserve(strToken))
                                    {
                                        modelTokenType.Lexem = strToken;
                                        modelTokenType.TokenType = 1;
                                        modelTokenType.TokenProperty = "保留字";
                                        this.arrayTokens.Add(modelTokenType);
                                    }
                                    else
                                    {
                                        modelTokenType.Lexem = strToken;
                                        modelTokenType.TokenType = 5;
                                        modelTokenType.TokenProperty = "标志符";
                                        this.arrayTokens.Add(modelTokenType);
                                    }
                                    return this.arrayTokens;

                                   
                                }
                                else
                                {
                                    this.ch = this.GetChar(sourceCodeChars, this.tokenIndexer);
                                   
                                }
                               
                            }

                            //保存识别出来的结果
                            modelTokenType = new ModelTokenType();
                            if (this.Reserve(strToken))
                            {
                                modelTokenType.Lexem = strToken;
                                modelTokenType.TokenType = 1;
                                modelTokenType.TokenProperty = "保留字";
                                this.arrayTokens.Add(modelTokenType);
                            }
                            else
                            {
                                modelTokenType.Lexem = strToken;
                                modelTokenType.TokenType = 5;
                                modelTokenType.TokenProperty = "标志符";
                                this.arrayTokens.Add(modelTokenType);
                            }

                            //指针回退一步
                           this.Retract();

                            strToken = "";

                            //将ch设置为空字符，使其跳出本次循环
                            this.ch = ' ';

                           
                        }
                        #endregion
                        
                       
                        #region(2).如果是以数字开头时，则判断为数字
                        //(1).如果是以字母开头时，则判断为保留字或者标识符
                        if (IsDigit(this.ch))
                        {
                            ModelTokenType modelTokenType;

                           while((IsDigit(this.ch))||(this.ch=='.'))
                           //while ((IsDigit(this.ch)))
                            {
                                strToken = strToken + ch;
                                this.tokenIndexer++;
                                if (this.tokenIndexer ==sourceCodeChars.Length)
                                {
                                    //保存识别出来的结果
                                    modelTokenType = new ModelTokenType();
                                    modelTokenType.Lexem = strToken;
                                    modelTokenType.TokenType = 4;
                                    modelTokenType.TokenProperty = "数字";
                                    this.arrayTokens.Add(modelTokenType);
                                    return this.arrayTokens;
                                }
                                else
                                {

                                    this.ch = this.GetChar(sourceCodeChars, this.tokenIndexer);
                                }
                            }


                            //保存识别出来的结果
                            modelTokenType = new ModelTokenType();
                            modelTokenType.Lexem = strToken;
                            modelTokenType.TokenType = 4;
                            modelTokenType.TokenProperty = "数字";
                            this.arrayTokens.Add(modelTokenType);

                            //指针回退一步
                           this.Retract();

                            strToken = "";

                            //将ch设置为空字符，使其跳出本次循环
                            this.ch = ' ';

                           
                        }
                        #endregion

                      
                        #region(3).判断是否为运算符
                        if (this.ch == '+'
                             || this.ch == '-'
                             || this.ch == '*'
                             || this.ch == '/'
                             || this.ch == '='
                             || this.ch == '<'
                             || this.ch == '>'
                             || this.ch == '!')
                        {

                            ModelTokenType modelTokenType;

                            while ((IsOporator(this.ch)))
                            {
                                strToken = strToken + ch;

                                this.tokenIndexer++;
                                if (this.tokenIndexer == sourceCodeChars.Length)
                                {

                                    //保存识别出来的结果
                                    modelTokenType = new ModelTokenType();
                                    modelTokenType.Lexem = strToken;
                                    modelTokenType.TokenType = 2;
                                    modelTokenType.TokenProperty = "运算符";
                                    this.arrayTokens.Add(modelTokenType);
                                    return this.arrayTokens;

                                   
                                }
                                else
                                {
                                    this.ch = this.GetChar(sourceCodeChars, this.tokenIndexer);
                                }
                            }

                            //保存识别出来的结果
                            modelTokenType = new ModelTokenType();
                            modelTokenType.Lexem = strToken;
                            modelTokenType.TokenType = 2;
                            modelTokenType.TokenProperty = "运算符";
                            this.arrayTokens.Add(modelTokenType);

                             //指针回退一步
                            this.Retract();

                            strToken = "";

                            //将ch设置为空字符，使其跳出本次循环
                            this.ch = ' ';


                           
                        }
                        #endregion

                        #region (4)判断是否为界符
                        if (this.ch == '('
                            || this.ch == ')'
                            || this.ch == '{'
                            || this.ch == '}'
                            || this.ch == '['
                            || this.ch == ']'
                            || this.ch == ','
                            || this.ch == ';'
                            || this.ch == ':'
                            || this.ch == '\\'
                            )
                        {
                            strToken = strToken + ch;
                            //保存识别出来的结果

                            ModelTokenType modelTokenType = new ModelTokenType();
                            modelTokenType.Lexem = strToken;
                            modelTokenType.TokenType = 3;
                            modelTokenType.TokenProperty = "界符";
                            this.arrayTokens.Add(modelTokenType);
                        }
                        #endregion


                    }

                    //指标后移一位
                   this.tokenIndexer++;

                    Console.WriteLine(strToken);
                }
                while (this.tokenIndexer < this.sourceCodeChars.Length);
                #endregion

                //添加到DataGrid
                //this.Add2DataGridView();
                return this.arrayTokens;

            }
            catch (Exception ex)
            {
                throw ex;
                //MessageBox.Show("错误：" + ex.Message + "请尝试关闭本窗口，并重新执行！", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion 
    }
}
